<?php

/**
 * @Author: Wang Chunsheng 2192138785@qq.com
 * @Date:   2020-03-12 23:31:55
 * @Last Modified by:   Wang Chunsheng 2192138785@qq.com
 * @Last Modified time: 2020-04-11 15:08:47
 */


namespace common\addons\diandi_shop\services;

use common\models\DdMember;
use api\modules\wechat\models\DdWxappFans;
use common\addons\diandi_shop\models\DdGoods;
use common\addons\diandi_shop\models\DdGoodsSpec;
use common\addons\diandi_shop\models\DdOrder;
use common\addons\diandi_shop\models\DdOrderAddress;
use common\addons\diandi_shop\models\DdOrderGoods;
use common\addons\diandi_shop\models\enums\OrderStatus;
use common\addons\diandi_shop\models\enums\PayStatus;
use common\addons\diandi_shop\models\searchs\DdShopAreas;
use common\helpers\ArrayHelper;
use common\helpers\ErrorsHelper;
use common\helpers\FileHelper;
use common\helpers\ImageHelper;
use common\helpers\ResultHelper;
use common\models\DdCorePaylog;
use common\models\DdRegion;
use common\models\DdUserAddress;
use common\services\BaseService;
use yii\helpers\Json;
use Yii;
use yii\data\Pagination;

class OrderService extends BaseService
{
    // 创建订单
    /**
     * Undocumented function
     *
     * @param [type] $user_id 用户id
     * @param [type] $total_price 订单总额
     * @param [type] $express_price 运费
     * @param [type] $express_type 地址类型 1配送点 2自由地址
     * @param [type] $name 姓名
     * @param [type] $phone 电话
     * @param [type] $detail 详情
     * @return void
     */
    public static function createOrder($user_id, $goods, $total_price, $express_price, $express_type, $address_id, $remark, $name, $phone, $delivery_time)
    {
        $express_price = $express_type == 0 ? $express_price : 0;
        // 订单基础信息写入
        $orderbase = [
            "order_no" => self::CreateOrderno(), //订单编号
            "total_price" => $total_price, //付款总额
            "pay_price" => $total_price + $express_price, //订单金额
            "pay_status" => PayStatus::NONPAYMENT, //支付状态
            "remark" => $remark, //订单备注
            // "pay_time" => $order['pay_time'], //付款时间
            "express_price" => $express_price, //运费
            // "express_company" => $order['express_company'], //快递公司
            // "express_no" => $order['express_no'], //快递号码
            // "delivery_status" => $order['delivery_status'], //发货状态
            // "delivery_time" => $order['delivery_time'], //发货时间
            // "receipt_status" => $order['receipt_status'], //收货状态
            // "receipt_time" => $order['receipt_time'], //收货时间
            "order_status" => OrderStatus::NONPAYMENT, //订单状态
            // "transaction_id" => $order['transaction_id'], //微信支付订单号
            "user_id" => $user_id //会员id
        ];

        $transaction = DdOrder::getDb()->beginTransaction();
        try {
            $DdOrder = new DdOrder();
            if ($DdOrder->load($orderbase, '') && $DdOrder->save()) {
                $order_id = $DdOrder->order_id;
                // 订单商品
                if ($goods) {

                    // 保存订单商品信息
                    $DdOrderGoods = new  DdOrderGoods();
                    $DdGoodsSpec = new DdGoodsSpec();
                    $goods_ids = array_column($goods, 'goods_id');
                    $specAll = $DdGoodsSpec::find()->where(['goods_id' => $goods_ids])->all();
                    foreach ($specAll as $key => $value) {
                        $goods_specs[$value['goods_id']][$value['spec_sku_id']] = $value;
                    }


                    foreach ($goods as $items) {
                        $item = $items['goods'];
                        $orderbase_body[] = $item['goods_name'];
                        $goods_spec = $goods_specs[$items['goods_id']][$items['spec_id']];
                        $goods_price = $items['goods_price'];
                        $line_price = $items['line_price'];
                        $total_num = $items['number'];
                        $goods_weight = empty($items['spec_id']) ? $item['goods_weight']  : $goods_spec['goods_weight'];
                        $goods_no =  empty($items['spec_id']) ? $item['goods_no']  : $goods_spec['goods_no'];                       
                        $total_price = $goods_price * $total_num;
                        $order_goods = [
                            'goods_id' => $item['goods_id'],
                            'goods_name' => $item['goods_name'],
                            'thumb' => $item['thumb'],
                            'deduct_stock_type' => $item['deduct_stock_type'],
                            'stock_up' => $item['deduct_stock_type'] == 10 ? 1 : 0,
                            'spec_type' => empty($item['spec_id']) ? 1 : 0,
                            'spec_sku_id' => $goods_specs[$item['goods_id']][$item['spec_id']]['spec_sku_id'],
                            'goods_spec_id' => $goods_specs[$item['goods_id']][$item['spec_id']]['goods_spec_id'],
                            'goods_attr' => $goods_specs[$item['goods_id']][$item['spec_id']]['spec_val'],
                            'content' => $item['content'] ? $item['content'] : 'rr',
                            'goods_no' => $goods_no,
                            'goods_price' => $goods_price,
                            'line_price' => $line_price,
                            'goods_weight' => $goods_weight,
                            'total_num' =>  $total_num,
                            'total_price' => $total_price,
                            'order_id' => $order_id,
                            'user_id' => $user_id,
                        ];
                        $_DdOrderGoods = clone $DdOrderGoods;
                        $_DdOrderGoods->setAttributes($order_goods);
                        $_DdOrderGoods->save();
                    }
                    // 校验库存并操作库存
                    self::stockReduce($goods);
                }
                $DdOrderAddress = new DdOrderAddress();
                // 0 外卖配送-取用户的地址  1上门取货-取配送点

                if ($express_type == 0) {
                    $areas = DdUserAddress::findOne(['address_id' => $address_id]);
                    $order_address = [
                        'name' => $areas['name'],
                        'phone' => $areas['phone'],
                        'province_id' => $areas['province_id'],
                        'city_id' => $areas['city_id'],
                        'region_id' => $areas['region_id'],
                        'detail' => $areas['detail'],
                        'delivery_time' => $delivery_time,
                        'order_id' => $order_id,
                        'user_id' => $user_id
                    ];
                    $DdOrderAddress->load($order_address, '');
                } else {
                    // 配送点取货或送货
                    $areas = DdShopAreas::findOne(['area_id' => $address_id]);
                    $order_address = [
                        'name' => $name,
                        'phone' => $phone,
                        'province_id' => $areas['province_id'],
                        'city_id' => $areas['city_id'],
                        'region_id' => $areas['region_id'],
                        'detail' => $areas['address'],
                        'delivery_time' => $delivery_time,
                        'order_id' => $order_id,
                        'user_id' => $user_id
                    ];
                    // 更新用户的名称和手机号
                    DdMember::updateAll(['username' => $name, 'mobile' => $phone], ['member_id' => $user_id]);
                    $DdOrderAddress->load($order_address, '');
                }
                $DdOrderAddress->save($order_address);
                // 订单收货地址
            }
            // 删除购物车
            CartService::clearAll($user_id);
            // 写入订单支付日志
            self::paylog($orderbase, $order_id);
            $transaction->commit();
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        } catch (\Throwable $e) {
            $transaction->rollBack();
            throw $e;
        }
        $orderbase['order_id'] = $order_id;
        $orderbase['body'] = $orderbase_body[0];
        return $orderbase;
    }

    // 减少库存
    public static function stockReduce($goods)
    {
        $path = __DIR__ . '/../log/order';
        if (!empty($goods) && is_array($goods)) {
            FileHelper::writeLog($path, '下单商品库存处理' . json_encode($goods));
            $DdGoods = new DdGoods();
            // 实时获取当前商品库存
            $goods_ids = array_column($goods, 'goods_id');
            // 获取所有的商品库存
            $stocks = $DdGoods->find()
                ->where(['goods_id' => $goods_ids])
                ->select(['stock', 'goods_id'])
                ->indexBy('goods_id')
                ->asArray()
                ->all();
            $DdGoodsSpec = new DdGoodsSpec();
            foreach ($goods as $item) {
                $_DdGoods  = clone $DdGoods;
                $_DdGoodsSpec  = clone $DdGoodsSpec;
                // 更新库存
                if ($item['deduct_stock_type'] == 10) {
                    // 实时库存
                    $stock = $stocks[$item['goods_id']]['stock'];
                    if ($item['number'] > $stock) {
                        throw new \Exception($item['goods_name'] . '库存不足');
                    }
                    $res = $_DdGoods::updateAllCounters(['stock' => -$item['number']], ['goods_id' => $item['goods_id']]);
                    FileHelper::writeLog($path, '下单商品库存处理结果' . json_encode($res));
                    FileHelper::writeLog($path, '更新数据' . json_encode([['stock' => -$item['number']], ['goods_id' => $item['goods_id']]]));
                    if (!empty($item['spec_id'])) {
                        $_DdGoodsSpec::updateAllCounters(
                            [
                                'stock_num' => -$item['number']
                            ],
                            [
                                'goods_id' => $item['goods_id'],
                                'spec_sku_id' => $item['spec_id']
                            ]
                        );
                    }
                }
            }
        }
    }


    /**
     * 订单操作
     *
     * @param [type] $order_id
     * @param [type] $ctype
     * @return void
     */
    public static function confirmOrder($order_id, $ctype)
    {
        $massage = '操作成功';
        switch ($ctype) {
            case 'qxdd';
                // 取消订单
                $res = DdOrder::updateAll(['order_status' => OrderStatus::getValueByName('已取消')], ['order_id' => $order_id]);
                $massage = '取消成功';
                break;
            case 'qrfh';
                // 确认发货
                $res = DdOrder::updateAll([
                    'order_status' => OrderStatus::getValueByName('已发货'),
                    'delivery_status' => 1,
                    'delivery_time' => time()
                ], ['order_id' => $order_id]);
                $massage = '付款成功';
                break;
            case 'qrsh';
                // 确认收货
                $res = DdOrder::updateAll([
                    'order_status' => OrderStatus::getValueByName('已收货'),
                    'receipt_status' => 1,
                    'receipt_time' => time()
                ], ['order_id' => $order_id]);
                $massage = '确认收货成功';
                break;
            case 'scdd';
                // 删除订单
                $DdOrder = new DdOrder();
                $DdOrderGoods = new DdOrderGoods();
                $DdOrderAddress = new DdOrderAddress();

                $DdOrder::deleteAll(['order_id' => $order_id]);
                $DdOrderGoods::deleteAll(['order_id' => $order_id]);
                $DdOrderAddress::deleteAll(['order_id' => $order_id]);
                $massage = '删除成功';

                break;
            case 'qrfk';
                // 确认付款
                $logPath = Yii::getAlias("@runtime/diandi_shop/log/order.log");
                $orders = DdOrder::findOne(['order_id' => $order_id]);
                OrderService::orderNotify($orders['order_no'], $orders['pay_price'], '', $logPath);
                $massage = '付款成功';
                break;
        }
        $orderinfo = self::detail($order_id);
        return  ResultHelper::json(200, $massage, $orderinfo);
    }

    // 立即付款
    public function pay()
    {
    }

    // 确认收货
    public function deliver()
    {
    }

    // 取消订单
    public function cancel()
    {
    }

    // 删除订单
    public function delete()
    {
    }

    // 订单列表
    public static function list($user_id, $order_status, $pageSize)
    {
        $page = Yii::$app->request->get('page');

        $where = []; //初始化条件数组
        $where['user_id'] = $user_id;
        if (is_numeric($order_status)) {
            $where['order_status'] = $order_status;
        }

        // 创建一个 DB 查询来获得所有
        $query = DdOrder::find()->where($where)->with('goods')->orderBy('create_time desc');

        // 得到订单的总数（但是还没有从数据库取数据）
        $count = $query->count();
        $pagination = new Pagination([
            'totalCount' => $count,
            'pageSize' => $pageSize
        ]);
        $list = $query->offset($pagination->offset)
            ->asArray()
            ->limit($pagination->limit)
            ->all();

        foreach ($list as &$item) {
            $item['create_time'] = date('m-d H:i:s', $item['create_time']);
            $item['status_label'] = OrderStatus::getLabel($item['order_status']);
        }
        return $list;
    }

    // 写入订单支付日志
    public static function paylog($order, $order_id)
    {
        $user_id = $order['user_id'];
        $fans = DdWxappFans::getFansByUid($user_id);
        $openid = $fans['openid'];
        $openid = $fans['openid'];
        $data = [
            'type' => 'wechat',
            'openid' => $openid,
            'uniontid' => $order['order_no'],
            // 'tid' =>  $order['order_no'],
            'fee' => $order['total_price'],
            'status' => 0,
            'module' => 'diandi_shop',
            'tag' => '小程序下单',
        ];
        $DdCorePaylog = new DdCorePaylog();
        $DdCorePaylog->load($data, '');
        $res = $DdCorePaylog->save();
        return $res;
    }

    /**
     * 付款成功后回调
     *
     * @param [type] $out_trade_no 订单编号
     * @param [type] $total_fee 总金额
     * @param string $transaction_id 微信单号
     * @param string $logPath 日志路径
     * @return void
     */
    public static function orderNotify($out_trade_no, $total_fee, $transaction_id = '', $logPath = '@api/modules/wechat/log/paynotify/wechat.log')
    {

        // $logPath =$is_app=='wechat'?'@api/modules/wechat/log/paynotify/wechat.log': '@backend/modules/diandi_shop/log/paynotify/wechat.log';

        // $transaction_id = $is_app=='wechat'?$params['transaction_id']:'';
        // $out_trade_no = $is_app=='wechat'?$params['out_trade_no']:$params['order_no'];
        // $total_fee = $is_app=='wechat'?$params['total_fee'] :$params['pay_price'];

        FileHelper::writeLog($logPath, '模块内回调' . $out_trade_no);
        //支付金额校验
        $orderInfo = DdOrder::findOne(['order_no' => $out_trade_no]);
        FileHelper::writeLog($logPath, '订单获取' . Json::encode($orderInfo));

        FileHelper::writeLog($logPath, '付款状态' . OrderStatus::getValueByName('已付款'));

        if ($orderInfo['order_status'] == OrderStatus::getValueByName('已付款') && !empty($transaction_id)) {
            return ArrayHelper::toXml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
        }
        $transaction = DdOrder::getDb()->beginTransaction();

        try {
            FileHelper::writeLog($logPath, '模块内回调1');
            // if ($orderInfo['pay_price'] * 100 != $total_fee) {
            //     return false;
            // }
            // 订单状态、微信支付订单号码更新修改
            DdOrder::updateAll([
                'order_status' => OrderStatus::getValueByName('已付款'),
                'pay_status' => 1,
                'pay_time' => time(),
                'transaction_id' => $transaction_id
            ], ['order_no' => $out_trade_no]);
            FileHelper::writeLog($logPath, '模块内回调2');

            // 支付减库存处理
            $order_goods = DdOrderGoods::find()->where([
                'order_id' => $orderInfo['order_id'],
                'user_id' => $orderInfo['user_id'],
                'stock_up' => 0,
                'deduct_stock_type' => 20,
            ])->select(['goods_id', 'total_num', 'goods_name'])->all();
            FileHelper::writeLog($logPath, '模块内回调3');

            $DdGoods = new DdGoods();
            $DdGoodsSpec = new  DdGoodsSpec();
            // 实时获取当前商品库存
            $goods_ids = array_keys(ArrayHelper::arrayKey($order_goods, 'goods_id'));
            FileHelper::writeLog($logPath, '所有商品id' . json_encode($goods_ids));
            FileHelper::writeLog($logPath, '所有商品' . json_encode($order_goods));

            // 获取所有的商品库存
            $stocks = $DdGoods->find()
                ->where(['goods_id' => $goods_ids])
                ->select(['stock', 'goods_id'])
                ->indexBy('goods_id')
                ->asArray()
                ->all();
            FileHelper::writeLog($logPath, '所有商品库存' . json_encode($stocks));
            if (!empty($order_goods)) {
                foreach ($order_goods as $item) {
                    $_DdGoods = clone $DdGoods;
                    $_DdGoodsSpec = clone $DdGoodsSpec;
                    // 更新库存
                    // 实时库存
                    $stock = $stocks[$item['goods_id']]['stock'];
                    FileHelper::writeLog($logPath, '实时' . $stock);
                    if ($item['total_num'] > $stock) {
                        FileHelper::writeLog($logPath, $item['goods_name'] . '库存不足');
                        throw new \Exception($item['goods_name'] . '库存不足');
                    }
                    $res = $_DdGoods::updateAllCounters(['stock' => -$item['total_num']], ['goods_id' => $item['goods_id']]);
                    FileHelper::writeLog($logPath, '下单商品库存处理结果' . json_encode($res));
                    FileHelper::writeLog($logPath, '更新数据' . json_encode([['stock' => -$item['total_num']], ['goods_id' => $item['goods_id']]]));
                    $_DdGoodsSpec::updateAllCounters(
                        [
                            'stock_num' => -$item['total_num']
                        ],
                        [
                            'goods_id' => $item['goods_id'],
                            'spec_sku_id' => $item['spec_sku_id']
                        ]
                    );
                }
            }

            FileHelper::writeLog($logPath, '库存处理完成');

            // 日志状态、微信支付订单号码更新修改
            DdCorePaylog::updateAll([
                'status' => 1,
                'tid' => $transaction_id
            ], ['uniontid' => $out_trade_no]);
            // 返回成功  
            FileHelper::writeLog($logPath, '支付回调返回成功');
            $transaction->commit();
        } catch (\Exception $e) {
            $transaction->rollBack();
            FileHelper::writeLog($logPath, '错误信息1' . Json::encode($e));
            throw $e;
        } catch (\Throwable $e) {
            $transaction->rollBack();
            FileHelper::writeLog($logPath, '错误信息2' . Json::encode($e));
            throw $e;
        }
    }

    // 订单详情
    public static function detail($id)
    {
        $DdOrder = new DdOrder();
        $detail = $DdOrder->find()
            ->with(['goods', 'address'])
            ->where(['order_id' => $id])
            ->asArray()->one();
        $region = DdRegion::find()->where(['id' => $detail['address']['region_id']])->select('merger_name')->one();
        $detail['address']['address_detail'] = $region['merger_name'];
        
        $total_nums = array_column($detail['goods'],'total_num');
        $detail['goods_total'] = array_sum($total_nums);

        $detail['pay_time']     = date('Y-m-d H:i:s', $detail['pay_time']);
        $detail['receipt_time'] = date('Y-m-d H:i:s', $detail['receipt_time']);
        $detail['create_time']  = date('Y-m-d H:i:s', $detail['create_time']);

        return $detail;
    }

    // 物流跟踪
    public function logistics()
    {
    }

    // 生成订单编号
    public static function CreateOrderno()
    {
        return date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
    }
}
